// $Id: text_processing.c 28 2015-03-11 01:53:12Z robim.poa@gmail.com $
//-----------------------------------------------------------------------------
// Purpose: Text processor and interpreter.
// $Rev: 28 $
// $Author: robim.poa@gmail.com $
// $Date: 2015-03-11 01:53:12 +0000 (Wed, 11 Mar 2015) $

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "debug.h"
#include "text_decoding.h"
#include "text_processing.h"

void tpReadExpression(struct tp_node_expression *tp_node_expression_head, int kind, struct tp_node_var *node_var_head, FILE *pfile)
{
	int quit = 0, parenthesis = 0, var_id, operator;
	char LastChar = '\0';
	char buffer[255];

	while(!quit)
	{
		if((tdLookNextChar(pfile)!='(') && (LastChar != ')'))
		{
			tdGetString(buffer, pfile);
			if(tdIsNumber(buffer))
			{
				tpCreateExpressionNode(tp_node_expression_head, EXPRESSION_TYPE_VALUE, tdStrToInt(buffer));
				printf("Value: %d\n", tdStrToInt(buffer));
			}
			else
			{
				var_id = tpCheckVarExistance(node_var_head, buffer);
				if(var_id>=0)
				{
					tpCreateExpressionNode(tp_node_expression_head, EXPRESSION_TYPE_VAR, var_id);
					printf("Variable: %s\n",buffer);
				}
				else
					printf("%d:error: '%s' undeclared\n", tdGetLine(pfile), buffer);
			}
		}
		LastChar = '\0';
		operator = tdGetOperator(buffer, pfile);
		switch(operator)
		{
			case LOGIC_OPERATOR_OR:
			case LOGIC_OPERATOR_AND:
			case LOGIC_OPERATOR_NOT:
			case COMPARISON_OPERATOR_EQUAL:
			case COMPARISON_OPERATOR_NEQUAL:
			case COMPARISON_OPERATOR_GREATER:
			case COMPARISON_OPERATOR_LESS:
			case COMPARISON_OPERATOR_GREATER_EQUAL:
			case COMPARISON_OPERATOR_LESS_EQUAL:
			case ARITHMETIC_OPERATOR_EQUAL:
			case ARITHMETIC_OPERATOR_PLUS:
			case ARITHMETIC_OPERATOR_MINUS:
			case ARITHMETIC_OPERATOR_MULTI:
			case ARITHMETIC_OPERATOR_DIVIS:
			case ARITHMETIC_OPERATOR_MODULO:
			case ARITHMETIC_OPERATOR_INCREMENT:
			case ARITHMETIC_OPERATOR_DECREMENT:
			case ARITHMETIC_OPERATOR_POWER:
				tpCreateExpressionNode(tp_node_expression_head, EXPRESSION_TYPE_OPERATOR, operator);
				break;

			case BRACKETS_PARENTHESES_OPEN:
				tpCreateExpressionNode(tp_node_expression_head, EXPRESSION_TYPE_OPERATOR, BRACKETS_PARENTHESES_OPEN);
				parenthesis++;
				break;

			case BRACKETS_PARENTHESES_CLOSE:
				tpCreateExpressionNode(tp_node_expression_head, EXPRESSION_TYPE_OPERATOR, BRACKETS_PARENTHESES_CLOSE);
				parenthesis--;
				LastChar = ')';
				if(parenthesis==-1 && kind==EXPRESSION_END_PARENTHESES)
					quit=1;
				break;

			case SYNTAX_MARK_SEMICOLON:
				if(kind == EXPRESSION_END_SEMICOLON)
				{
					quit=1;
				}
				break;

			default:
				printf("%d:error: expected operator before %s\n", tdGetLine(pfile), buffer);
		}
	}
}

void tpCreateExpressionNode(struct tp_node_expression *tp_node_expression_head, int type, int data)
{
	struct tp_node_expression *tp_node_expression_tail, *tp_node_expression_new;
	tp_node_expression_tail = tp_node_expression_head;

	while(tp_node_expression_tail->next!=NULL)
		tp_node_expression_tail = tp_node_expression_tail->next;

	tp_node_expression_new = (struct tp_node_expression*) malloc(sizeof(struct tp_node_expression));
	tp_node_expression_new->type = type;
	tp_node_expression_new->data = data;
	tp_node_expression_new->next = NULL;

	tp_node_expression_tail->next = tp_node_expression_new;
}

void tpCreateVarNode(struct tp_node_var *nodep_var_head, char *buffer, int char_type)
{
	unsigned int id = 0;

	struct tp_node_var *nodep_var_tail, *nodep_var_new;
	
	nodep_var_tail = nodep_var_head;
	while(nodep_var_tail->next != NULL)
	{
		id++;
		nodep_var_tail = nodep_var_tail->next;
	}
	
	nodep_var_new = (struct tp_node_var*) malloc(sizeof(struct tp_node_var));
	strcpy(nodep_var_new->name, buffer);
	nodep_var_new->id = id;
	nodep_var_new->type = char_type;
	nodep_var_new->next = NULL;
	nodep_var_tail->next = nodep_var_new;
}

int tpCheckVarExistance(struct tp_node_var *nodep_var_head, char* buffer)
{
	struct tp_node_var *nodep_var_aux;

	nodep_var_aux = nodep_var_head;
	while(nodep_var_aux->next != NULL)
	{
		nodep_var_aux = nodep_var_aux->next;
		if(!strcmp(buffer,nodep_var_aux->name))
		{
			return nodep_var_aux->id;
		}
	}
	return -1;
}